﻿using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.IdentityModel.Tokens;
using System.IdentityModel.Tokens.Jwt;
using System.Text;

namespace FastEasy.Common.Jwt
{
    public static class BearerModule
    {
        /// <summary>
        /// Bearer认证服务
        /// </summary>
        /// <param name="Services"></param>
        public static void AddBearerModule(this IServiceCollection Services)
        {
            Services.AddAuthentication("Bearer").AddJwtBearer(s =>
            {
                var iss = "FastEasy";
                var aud = "all";
                var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("zhanzhanghuaqwyehsydghuaqwyehsyd"));
                var code = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);

                s.TokenValidationParameters = new TokenValidationParameters
                {
                    ValidateIssuer = true,//校验发行人
                    ValidateAudience = true,//校验受众人
                    ValidateIssuerSigningKey = true,//校验密钥
                    ValidateLifetime = true,//校验有效期
                    ValidIssuer = iss,
                    ValidAudience = aud,
                    IssuerSigningKey = key,
                    ClockSkew = TimeSpan.FromSeconds(30),//过期偏移量
                    RequireExpirationTime = true //校验token是否有过期时间
                };

                s.Events = new Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerEvents()
                {
                    //当JWT Bearer认证失败时，即请求未包含有效的JWT令牌或令牌验证失败，该事件会被触发
                    OnChallenge = context =>
                    {
                        context.Response.Headers.Add("Token-Error", context.ErrorDescription);
                        return Task.CompletedTask;
                    },
                    //当JWT Bearer认证过程中出现异常时，例如令牌过期、签名验证失败等情况，该事件会被触发
                    OnAuthenticationFailed = context =>
                    {
                        //通过请求头获取到Token
                        var token = context.Request.Headers.Authorization.ToString()
                        .Replace("Bearer ", string.Empty).Replace("bearer", string.Empty).Trim();

                        //解析token
                        var jwtHandler = new JwtSecurityTokenHandler();
                        var jwtToken = jwtHandler.ReadJwtToken(token);

                        //发行人不匹配
                        if (jwtToken.Issuer != "发行人")
                        {
                            context.Response.Headers.Add("Token-Error-Iss", "IssError!");
                        }
                        //受众人不匹配
                        if (jwtToken.Audiences.FirstOrDefault() != "受众人")
                        {
                            context.Response.Headers.Add("Token-Error-Aud", "AudError!");
                        }
                        //过期
                        if (context.Exception.GetType() == typeof(SecurityTokenExpiredException))
                        {
                            context.Response.Headers.Add("Token-Error-Exp", "True");
                        }
                        return Task.CompletedTask;
                    }
                };
            });
        }

        /// <summary>
        /// 启用Bearer认证
        /// </summary>
        /// <param name="app"></param>
        public static void UseBearerModule(this IApplicationBuilder app)
        {
            app.UseAuthentication();
            app.UseAuthorization();
        }
    }
}